package com.kye.express.business.score;

import android.annotation.SuppressLint;
import android.support.annotation.IdRes;

import com.kye.base.Logger;
import com.kye.express.App;
import com.kye.express.R;
import com.kye.express.contract.base.BasePresenter;
import com.kye.express.contract.base.view.ErrorView;
import com.kye.express.contract.base.view.IView;
import com.kye.express.contract.base.view.LoadingView;
import com.kye.model.OpenApiResultObserver;
import com.kye.model.UserSession;
import com.kye.model.base.RetrofitManager;
import com.kye.model.bean.OpenApiResult;
import com.kye.model.bean.logistics.LogisticsDriverInfoBean;
import com.kye.model.bean.logistics.RequestLogisticsDriverInfo;
import com.kye.model.bean.score.RequestPostScore;
import com.kye.model.bean.user.User;
import com.kye.model.datasource.LogisticsDataSource;
import com.kye.model.service.ScoreService;

import java.util.ArrayList;
import java.util.List;

import io.reactivex.Observable;
import io.reactivex.ObservableSource;
import io.reactivex.Single;
import io.reactivex.SingleObserver;
import io.reactivex.SingleSource;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function;
import io.reactivex.functions.Predicate;
import io.reactivex.schedulers.Schedulers;
import me.zhanghai.android.materialratingbar.MaterialRatingBar;

public interface ScoreContract {

    interface ScoreView extends IView, LoadingView, ErrorView {

        void onUser(User user);

        List<ScoreTagModel> getScoreTagModelsLevel1();

        List<ScoreTagModel> getScoreTagModelsLevel2();

        List<ScoreTagModel> getScoreTagModelsLevel3();

        List<ScoreTagModel> getScoreTagModelsLevel4();

        List<ScoreTagModel> getScoreTagModelsLevel5();

        List<ScoreTagModel> getScoreTagModelsLevel0();

        void updateScoreRatingTags(List<ScoreTagModel> scoreTagModels, int rating);

        String getCode();

        void postScoreSuccess(OpenApiResult<Object> result, String message);

        void postScoreFailed(String msg);

        void setScoreTagSelected(List<ScoreTagModel> scoreTagSelected);

        void getLogisticsDriverInfoSuccess(LogisticsDriverInfoBean logisticsDriverInfoBean);

        void getLogisticsDriverInfoFailed(String msg);

        void getLogisticsDriverInfoFailedNet(String message);
    }

    class ScorePresenter extends BasePresenter<ScoreView> {

        private ScoreService scoreService;
        private LogisticsDataSource logisticsDataSource;

        public ScorePresenter() {
            scoreService = RetrofitManager.getInstance().createOpenApiService(ScoreService.class);
            logisticsDataSource = new LogisticsDataSource();
        }

        @Override
        public void bind(ScoreView view) {
            super.bind(view);
            UserSession.getInstance()
                    .getUserForRx()
                    .compose(getView().bindToLifecycleDestroy())
                    .subscribe(new Consumer<User>() {
                        @Override
                        public void accept(User user) throws Exception {
                            getView().onUser(user);
                        }
                    });
        }

        /**
         * 获取司机信息
         *
         * @param phone
         * @param orderCode
         */
        public void getLogisticsDriverInfo(String phone, String orderCode) {
            logisticsDataSource
                    .getLogisticsDriverInfo(new RequestLogisticsDriverInfo(phone, orderCode, "0"))
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(new OpenApiResultObserver<LogisticsDriverInfoBean>() {
                        @Override
                        public void onLoading(Disposable d) {

                        }

                        @Override
                        public void onSuccess(OpenApiResult<LogisticsDriverInfoBean> result, LogisticsDriverInfoBean logisticsDriverInfoBean) {
                            getView().getLogisticsDriverInfoSuccess(logisticsDriverInfoBean);
                        }

                        @Override
                        public void onApiError(OpenApiResult<LogisticsDriverInfoBean> result, int code, String msg) {
                            getView().getLogisticsDriverInfoFailed(msg);
                        }

                        @Override
                        public void onOtherError(Throwable e) {
                            getView().getLogisticsDriverInfoFailedNet(e.getMessage());
                        }

                        @Override
                        public void onLoaded() {

                        }
                    });
        }

        @SuppressLint("ResourceType")
        public Single<List<ScoreTagModel>> getScoreLevel1DataObservableByResArrayId(@IdRes int tagResId) {
            return
                    Observable.just(App.getContext().getResources().getStringArray(tagResId))
                            .flatMap(new Function<String[], ObservableSource<String>>() {
                                @Override
                                public ObservableSource<String> apply(String[] tags) throws Exception {
                                    return Observable.fromArray(tags);
                                }
                            })
                            .map(new Function<String, ScoreTagModel>() {
                                @Override
                                public ScoreTagModel apply(String tag) throws Exception {
                                    return new ScoreTagModel(tag, false);
                                }
                            })
                            .toList();
        }

        @SuppressLint("ResourceType")
        public void showScoreRatingData(MaterialRatingBar ratingBar, float rating) {
            Single<List<ScoreTagModel>> scoreLevelCurrent = null;
            Single<List<ScoreTagModel>> scoreLevel0 = null;
            Single<List<ScoreTagModel>> scoreLevel1 = getScoreLevel1DataObservableByResArrayId(R.array.score_level_1);
            Single<List<ScoreTagModel>> scoreLevel2 = getScoreLevel1DataObservableByResArrayId(R.array.score_level_2);
            Single<List<ScoreTagModel>> scoreLevel3 = getScoreLevel1DataObservableByResArrayId(R.array.score_level_3);
            Single<List<ScoreTagModel>> scoreLevel4 = getScoreLevel1DataObservableByResArrayId(R.array.score_level_4);
            Single<List<ScoreTagModel>> scoreLevel5 = getScoreLevel1DataObservableByResArrayId(R.array.score_level_5);
            List<ScoreTagModel> tags = new ArrayList<>();
            switch (Float.valueOf(rating).intValue()) {
                case 0:
                    scoreLevel0 = Single.just(getView().getScoreTagModelsLevel0());
                    scoreLevelCurrent = scoreLevel0;
                    break;
                case 5:
                    if (getView().getScoreTagModelsLevel1() != null && getView().getScoreTagModelsLevel1().size() > 0) {
                        scoreLevel1 = Single.just(getView().getScoreTagModelsLevel1());
                    }
                    scoreLevelCurrent = scoreLevel1;
                    break;
                case 4:
                    if (getView().getScoreTagModelsLevel2() != null && getView().getScoreTagModelsLevel2().size() > 0) {
                        scoreLevel2 = Single.just(getView().getScoreTagModelsLevel2());
                    }
                    scoreLevelCurrent = scoreLevel2;
                    break;
                case 3:
                    if (getView().getScoreTagModelsLevel3() != null && getView().getScoreTagModelsLevel3().size() > 0) {
                        scoreLevel3 = Single.just(getView().getScoreTagModelsLevel3());
                    }
                    scoreLevelCurrent = scoreLevel3;
                    break;
                case 2:
                    if (getView().getScoreTagModelsLevel4() != null && getView().getScoreTagModelsLevel4().size() > 0) {
                        scoreLevel4 = Single.just(getView().getScoreTagModelsLevel4());
                    }
                    scoreLevelCurrent = scoreLevel4;
                    break;
                case 1:
                    if (getView().getScoreTagModelsLevel5() != null && getView().getScoreTagModelsLevel5().size() > 0) {
                        scoreLevel5 = Single.just(getView().getScoreTagModelsLevel5());
                    }
                    scoreLevelCurrent = scoreLevel5;
                    break;
            }
            scoreLevelCurrent
                    .compose(getView().bindToLifecycleDestroy())
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(new SingleObserver<List<ScoreTagModel>>() {
                        @Override
                        public void onSubscribe(Disposable d) {
                            ratingBar.setEnabled(false);
                        }

                        @Override
                        public void onSuccess(List<ScoreTagModel> scoreTagModels) {
                            ratingBar.setEnabled(true);
                            getView().updateScoreRatingTags(scoreTagModels, (int) rating);
                        }

                        @Override
                        public void onError(Throwable e) {
                            ratingBar.setEnabled(true);
                        }
                    });

        }

        /**
         * 提交评分
         *
         * @param postScore
         * @param userInfo
         * @param scoreTagModels
         * @param rating
         * @param message
         */
        public void postScore(ScoreType postScore, User userInfo, List<ScoreTagModel> scoreTagModels, int rating, String message) {
            Observable.fromIterable(scoreTagModels)
                    .observeOn(Schedulers.io())
                    // 获取选中的
                    .filter(new Predicate<ScoreTagModel>() {
                        @Override
                        public boolean test(ScoreTagModel scoreTagModel) throws Exception {
                            return scoreTagModel.isSelected();
                        }
                    })
                    .toList()
                    .doOnSuccess(new Consumer<List<ScoreTagModel>>() {
                        @Override
                        public void accept(List<ScoreTagModel> scoreTagModels) throws Exception {
                            Logger.d("list : " + scoreTagModels);
                            getView().setScoreTagSelected(scoreTagModels);
                        }
                    })
                    // 获取flag '123'
                    .map(new Function<List<ScoreTagModel>, List<ScoreTagModel>>() {
                        @Override
                        public List<ScoreTagModel> apply(List<ScoreTagModel> scoreTagModels) throws Exception {
                            return scoreTagModels;
                        }
                    })
                    .map(new Function<List<ScoreTagModel>, String>() {
                        @Override
                        public String apply(List<ScoreTagModel> scoreTagModels) throws Exception {
                            StringBuilder flagBuilder = new StringBuilder();
                            for (ScoreTagModel tagModel : scoreTagModels) {
                                if (tagModel.isSelected()) {
                                    int position = scoreTagModels.indexOf(tagModel);
                                    flagBuilder.append(position + 1);
                                }
                            }
                            return flagBuilder.toString();
                        }
                    })
                    .map(new Function<String, RequestPostScore>() {
                        @Override
                        public RequestPostScore apply(String flags) throws Exception {
                            RequestPostScore requestPostScore = new RequestPostScore();
                            requestPostScore.setFlag(flags);
                            requestPostScore.setCode(getView().getCode());
                            requestPostScore.setPhone(userInfo.getPhone());
                            requestPostScore.setRemark(message);
                            // 类型（0为取货展示，1为派货展示）
                            requestPostScore.setType(postScore == ScoreType.TYPE_ORDER ? "0" : "1");
                            // 评分(1-满意，2-一般，3-不满意，4-很不满意 5-非常不满意)
                            requestPostScore.setScore(String.valueOf(6 - rating));
                            return requestPostScore;
                        }
                    })
                    // test
                    .doOnSuccess(new Consumer<RequestPostScore>() {
                        @Override
                        public void accept(RequestPostScore requestPostScore) throws Exception {
//                            Logger.d("requestPostScore:\n" + GsonUtils.toJsonString(requestPostScore, true));
//                            throw new RuntimeException("test");
                        }
                    })
                    .flatMap(new Function<RequestPostScore, SingleSource<OpenApiResult<Object>>>() {
                        @Override
                        public SingleSource<OpenApiResult<Object>> apply(RequestPostScore requestPostScore) throws Exception {
                            return scoreService
                                    .postScore(requestPostScore)
                                    .compose(getView().bindToLifecycleDestroy());

                        }
                    })
                    .subscribeOn(Schedulers.io())
                    .observeOn(AndroidSchedulers.mainThread())
                    .subscribe(new OpenApiResultObserver<Object>() {
                        @Override
                        public void onLoading(Disposable d) {
                            getView().onLoading();
                        }

                        @Override
                        public void onSuccess(OpenApiResult<Object> result, Object o) {
                            getView().postScoreSuccess(result, message);
                        }

                        @Override
                        public void onApiError(OpenApiResult<Object> result, int code, String msg) {
                            getView().postScoreFailed(msg);
                        }

                        @Override
                        public void onOtherError(Throwable e) {
                            getView().postScoreFailed(e.getMessage());
                        }

                        @Override
                        public void onLoaded() {
                            getView().onLoaded();
                        }
                    });

        }


    }
}
